<template>
    <rx-dialog @handOk="handSave" @cancel="cancel">
        <a-form :form="form" class="rx-menu-form">
            <a-form-item style="display:none">
                <a-input :value="form.typeId"/>
            </a-form-item>
            <div class="x-authorize-layout">
                <div class="x-authorize-layout-item" v-for="item of menuConfig">
                    <div class="x-item-title">{{ item.title }}</div>
                    <div class="x-layout-contents">
                        <div class="x-item-header">
                            <div class="x-item-search">
                                <a-input placeholder="搜索关键字" @change="menuSearch($event,item)" allowClear>
                                    <a-icon slot="prefix" type="search" />
                                </a-input>
                            </div>
                            <div class="x-item-toolbar">
                                <a-checkbox :checked="item.checkAll" @change="onChange($event,item)">
                                    {{$ti18('rxList.selectAll','全选')}}
                                </a-checkbox>
                                <a-checkbox :checked="item.checkStrictly" @change="changeCheckStrictly($event,item)">
                                    {{i18n('cascadeSelect','级联选择')}}
                                </a-checkbox>
                            </div>
                        </div>
                        <div class="x-item-content">
                            <div class="x-item-roll-box">
                                <rx-vue-tree
                                    :tree-data="item.searchData.length > 0? item.searchData : treeData[item.key]"
                                    v-model="item.checkedKeys"
                                    :show-checkbox="true"
                                    :check-strictly="item.checkStrictly"
                                    :showIcon="true"
                                    @selectChange="(checked,tree,parentData)=>selectChange({checked,tree,parentData,config:item})"
                                >
                                </rx-vue-tree>
                            </div>
                        </div>
                    </div>
                </div>

            </div>
        </a-form>
    </rx-dialog>
</template>

<script>
import SysMenuApi from '@/api/system/core/sysMenu'
import OsInstTypeMenuApi from '@/api/user/org/osInstTypeMenu'
import OsInstTypeApi from '@/api/user/org/osInstType'
import {BaseForm, Util, RxVueTree} from "@lowcode/jpaas-common-lib"
import { debounce, cloneDeep } from 'lodash-es'

export default {
    name: 'OsInstTypeMenuEdit',
    mixins: [BaseForm],
    components: {
        RxVueTree
    },
    data() {
        return {
            menuConfig:[
                {
                    key:'front',
                    title:this.ti18n('front','前端资源授权'),
                    checkAll:false,
                    checkStrictly:true,
                    checkedKeys:[],
                    searchData:[]
                },
                {
                    key:'backend',
                    title:this.ti18n('backend','后端资源授权'),
                    checkAll:false,
                    checkStrictly:true,
                    checkedKeys:[],
                    searchData:[]
                }
            ],
            /*
            * 前/后端树形数据
            * */
            treeData:{
                front:[],
                backend:[]
            },
            /*
            * 全部数据的平铺展示
            * id:{}
            * */
            allData:{},
            permissionIds:[]
        }
    },
    computed:{
        fronts(){
            /*前端平铺数据*/
            return this.tile('front')
        },
        backends(){
            /*后端平铺数据*/
            return this.tile('backend')
        }
    },
    created() {
        this.loadPermissions()
    },
    methods: {
        ti18n(name,text,key){
            return this.$ti18(name, text, "osGroupPrivilege", key);
        },
        i18n(name,text,key){
            return this.$ti18(name,text,"osInstType",key);
        },
        tile(type){
            let data = this.treeData[type];
            let arr = [];
            if(data){
                let loop = (list)=>{
                    for (let item of list){
                        if(!arr.includes(item.key)){
                            arr.push(item.key)
                        }
                        if(item.children && item.children.length > 0){
                            loop(item.children)
                        }
                    }
                }
                loop(data);
            }
            return arr;
        },
        filterTree(list,value){
            let data = list.filter(item=>{
                let isMatch = item.title.includes(value);
                if(item.children && item.children.length > 0){
                    item.children = this.filterTree(item.children,value);
                }
                return isMatch || item.children.length > 0
            })
            if(data.length > 0){
                return data
            }
            return []
        },
        menuSearch:debounce(function (e,item) {
            let { value } = e.target;
            let { treeData } = this;
            item.searchData = this.filterTree(cloneDeep(treeData[item.key]),value)
            if(value && item.searchData.length === 0){
                this.$message.warning(this.ti18n('noData','查询不到数据'))
            }
        },500),

        getParentNode(obj, id,filed){
            let getParent = (list, id) => {
                for (let item of list) {
                    if (item[filed] === id) {
                        return [item]
                    }
                    if (item.children) {
                        let node = getParent(item.children, id,filed);
                        if (node !== undefined) {
                            return node.concat(item)
                        }
                    }
                }
            }
            return getParent(obj, id)
        },
        selectChange({checked,tree,config}){
            //节点选中 同时选中父级节点；
            if(checked){
                let parenNode = this.getParentNode(this.treeData[config.key],tree['key'],'key');
                parenNode.forEach(item =>{
                    if(!config.checkedKeys.includes(item.key)){
                        config.checkedKeys.push(item.key);
                    }
                })
            }
        },
        get(id) {
            return OsInstTypeApi.get(id);
        },
        onload_(values) {
            if (values && values.typeId) {
                this.instTypeId = values.typeId
                let self_ = this;
                OsInstTypeMenuApi.findMenusByInstTypeId({instTypeId: values.typeId}).then(res => {
                    // 因为antd 树插件勾选父节点会导致所有子节点选中,所以过滤所有父节点
                    let data = res.data;
                    if(Array.isArray(data) && data.length === 0){
                        self_.permissionIds = []
                        return
                    }
                    // 将有权限的菜单收集起来
                    self_.permissionIds = data.map(item => item.id)
                    this.handlePermissionMenu()

                })
            }
        },
        changeCheckStrictly(e,item) {
            item.checkStrictly = e.target.checked;
        },
        handlePermissionMenu(){
            let { fronts,backends, menuConfig } = this;
            let keys = this.permissionIds.reduce((p,id)=>{
                let isBack = backends.includes(id)
                let key = isBack? 'backend':'front';
                p[key]? p[key].push(id) : p[key] = [id];
                return p
            },{});
            for (let item of menuConfig) {
                let selectKey = keys[item.key] ?? [];
                let _data = item.key === 'front'? fronts : backends;
                item.checkedKeys = [...selectKey];
                if(selectKey.length === _data.length && selectKey.length > 0){
                    item.checkAll = true;
                }
            }
        },
        handSave(e) {
            const { allData } = this;
            const _this = this;
            let data = [];
            for (let item of this.menuConfig){
                item.checkedKeys.forEach(id=>{
                    let o = allData[id];
                    if(o){
                        data.push({
                            menuId: o.id,
                            appId: o.appId,
                            name: o.name,
                            parentId: o.parentId,
                            remarks: o.remarks
                        });
                    }
                })
            }
            OsInstTypeMenuApi.saveOsInstTypeMenu(this.instTypeId, data).then(res => {
                e.loading = false;
                if (res.success) {
                    Util.closeWindow(_this, "ok");
                }
            })
        },
        loadPermissions() {
            SysMenuApi.selectMenus({type: 'inst'}).then(res => {
                let treeData = this.buildTree(res, '0');
                this.treeData = treeData.reduce((p,n)=>{
                    let key = n.appType === 0?'backend':'front';
                    p[key] ? p[key].push(n) : p[key] = [n];
                    return p
                },{})
                //this.handlePermissionMenu()
            })
        },
        buildTree(list, parentId = "0") {
            let treeList = list.filter(item =>{
                this.allData[item.id] = item;
                return item.parentId === parentId
            }).map(item => {
                    this.allData[item.id] = item;
                    return {
                        key: item.id,
                        title: item.name,
                        appType:item.appType,
                        slots: {icon: item.menuType},
                        children: this.buildTree(list, item.id)
                    }
                });
            return treeList.sort((app1,app2)=>{
               return app1.sn - app2.sn;
            });
        },
        onChange(e,item) {
            item.checkAll = e.target.checked;
            if (item.checkAll) {
                let data = this[item.key === 'front'?'fronts':'backends'];
                if(item.checkedKeys.length !== data.length){
                    for (let k of data){
                        if(!item.checkedKeys.includes(k)){
                            item.checkedKeys.push(k)
                        }
                    }
                }
            }else {
                item.checkedKeys = [];
            }
        }
    },
    watch:{
        fronts(){
            this.handlePermissionMenu();
        },
        backends(){
            this.handlePermissionMenu();
        }
    }
}
</script>

<style scoped>
.rx-menu-form{
    display: block;
    height: 100%;
    width: 100%;
}
.x-item-title{
    font-weight: 700;
    padding-bottom: 8px;
    color: rgba(0, 0, 0, 0.85);
}
.x-item-toolbar{
    padding: 6px 0;
}
.x-authorize-layout{
    height: inherit;
    width: inherit;
    display: flex;
    gap: 0 20px;
}
.x-layout-contents,
.x-authorize-layout-item{
    flex: 1;
    display: flex;
    flex-direction: column;
}
.x-layout-contents{
    border:1px solid #e8e8e8;
    border-radius: 6px;
}
.x-item-content{
    flex: 1;
    position: relative;
}
.x-item-roll-box{
    position: absolute;
    inset: 0;
    padding: 10px;
    overflow:scroll;
}

.x-item-header{
    padding: 10px 10px 0;
}
</style>
